<?php 

/**
* Syntax Highlighting Functions
*/
function app_highlight($source_code)
{
	if(!APP_LINE_NUMBERS == 1)
		return app_highlight_without_lines($source_code);
	else
		return app_highlight_with_lines($source_code);
}


function app_highlight_without_lines($source_code)
{
	return highlight_string("<?php\n" . $source_code . "\n?>", true);
}

function app_highlight_with_lines($source_code)
{
	//credit: http://www.php.net/manual/en/function.highlight-string.php#83824
	if (is_array($source_code))
		return false;

	$source_code = explode("\n", str_replace(array("\r\n", "\r"), "\n", $source_code));
	$line_count = 1;

	foreach ($source_code as $code_line)
	{
		$err = '&nbsp;&nbsp;'; //place holder
		global $app_error;
		$c = count($app_error);
		
		$errExists = false;
		
		for($i = 0; ($i < $c) && !$errExists; $i++)
		{
			
			if($app_error[$i]['line'] == $line_count)
			{
				if($app_error[$i]['type'] == 'Notice')
					$src = 'notice.png';
				else if($app_error[$i]['type'] == 'Warning')
					$src = 'warning.png';
				else
					$src = 'error.ico';
				
				$err = '<a 
							href="http://google.com/search?q=' . urlencode('php ' . $app_error[$i]['message']) . '"
							target="_blank">
								<img src="' . APP_TEMPLATE . '/images/' . $src . '"
								 width="16" height="16" border="0" 
								 title="'.$app_error[$i]['type'].'" 
								 alt="'.$app_error[$i]['type'].'" />
						</a>';
				$errExists = true;
			}
		}
		
		$formatted_code .= '<tr><td>'.$err.'</td><td>'.$line_count.'</td>';
		$line_count++;

		if (ereg('<\?(php)?[^[:graph:]]', $code_line))
			$formatted_code .= '<td>'. str_replace(array('<code>', '</code>'), '', highlight_string($code_line, true)).'</td></tr>';
		else
			$formatted_code .= '<td>'.ereg_replace('(&lt;\?php&nbsp;)+', '', str_replace(array('<code>', '</code>'), '', highlight_string('<?php '.$code_line, true))).'</td></tr>';
	}

	return '<table style="font: 1em Consolas, \'andale mono\', \'monotype.com\', \'lucida console\', monospace;">'.$formatted_code.'</table>';
}

/**
* Page Element Functions
*/

$GLOBALS['app_elements'] = array();

function app_register_element($file, $position)
{
	$GLOBALS['app_elements'][$position] = $file;
}

function app_get_elements()
{
	$app_elements = $GLOBALS['app_elements'];
	return  $app_elements;
}

function app_output($code, $mode)
{
	if($mode == 'code')
		return "<code>\n" . str_replace("\n", '<br />', htmlspecialchars($code)) . "\n</code>";
		
	return $code;
}

/**
* Eval Functions
*/

function app_eval($app_code)
{
	set_error_handler('app_error_handler');
		$app_pre = 'ob_start();';
		$app_post = '$apparatusOutput = ob_get_clean();';
		eval($app_pre . $app_code . $app_post);	
	restore_error_handler();
	$app_output = $apparatusOutput;
	
	return $app_output;
}

function app_error_handler($errno, $errstr, $errfile, $errline)
{
	global $app_error;
	
	switch($errno)
	{
		case E_PARSE:
		case E_ERROR:
		case E_COMPILE_ERROR:
		case E_USER_ERROR:
			$app_error[] = array('type' => 'Error', 'message' => $errstr, 'line' => $errline);
		break;
		case E_WARNING:
		case E_COMPILE_WARNING:
		case E_USER_WARNING:
			$app_error[] = array('type' => 'Warning', 'message' => $errstr, 'line' => $errline);
		break;
		case E_NOTICE:
		case E_USER_NOTICE:
			$app_error[] = array('type' => 'Notice', 'message' => $errstr, 'line' => $errline);
		break;
		default:
			$app_error[] = array('type' => 'Unknown', 'message' => $errstr, 'line' => $errline);
	}
	return true;
}

/**
* Version Functions
*/

//checks if a newer version is available
function app_check_version()
{
	//TODO
}

//Compares two version strings, returns 1 if test is >, 0 if =, -1 if <
//Only works with numeric version strings (ie #.#... ex 3.1.2)
function app_version_compare($test, $current)
{

	$currArr = explode('.', $current);
	$testArr = explode('.', $test);
	$testCount = count($testArr);
	$currCount = count($currArr);
	
	//select the string with the fewest elements
	$c = ($testCount < $currCount) ? $testCount : $currCount;

	//scan the string from major to minor
	for($i = 0; $i < $c; $i++)
	{
		//if the ith element of test is greater than curr
		if((int)$testArr[$i] > (int)$currArr[$i])
			return 1;
		else if((int)$testArr[$i] < (int)$currArr[$i])
			return -1;
	}

	//so far they are equal

	//if test has more elements than curr
	if($testCount > $currCount)
		return 1;
	else if($testCount < $currCount)
		return -1;
	
	//if we make it this far they are equal
	return 0;
}